/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package spatialmarketplace.cem.dao.implementation;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.sourceforge.stripes.util.Log;
import spatialmarketplace.cem.dao.DBHandler;
import spatialmarketplace.cem.dao.ForumPostDao;
import spatialmarketplace.cem.model.ForumPost;
import spatialmarketplace.cem.model.User;

/**
 * Implements the DAO for the forum Post.
 * @author Camila
 */
public class ForumPostDaoImpl implements ForumPostDao {

    private static final Log logger = Log.getInstance(ForumPostDaoImpl.class);
    private Connection conn = null;
    private static ForumPostDaoImpl instance = new ForumPostDaoImpl();

    public static ForumPostDaoImpl getInstance() {
        return instance;
    }

    /**
     * Retrieves the forum for a group having its ID.
     * @param groupId
     * @return list of posts of the selected forum.
     */
    @Override
    public ArrayList<ForumPost> readGroupForum(Integer groupId) {
        DBHandler dbInstance = DBHandler.getInstance();
        ArrayList<ForumPost> list = new ArrayList<ForumPost>();
        ForumPost forumPost;
        Integer idPost;
        Integer likeCount;
        String text;
        boolean isReported;
        boolean isLiked;
        Integer userId;
        Date date;

        //Added fields for business logic
        String userPhoto;
        String UserName;

        try {
            if (dbInstance != null) {
                String query = new String("SELECT * FROM ForumPost WHERE groupId = " + groupId + " AND belongsToGroup = true");

                dbInstance.openConnection();
                ResultSet rs = dbInstance.executeQuery(query);

                try {
                    while (rs.next()) {
                        idPost = Integer.valueOf(rs.getInt("idPost"));
                        likeCount = Integer.valueOf(rs.getInt("likeCount"));
                        text = rs.getString("text");
                        isReported = rs.getBoolean("isReported");
                        isLiked = rs.getBoolean("isLiked");
                        userId = Integer.valueOf(rs.getInt("userId"));
                        date = rs.getDate("date");

                        //Call User to find out name and photo
                        User tmp = UserDaoImpl.getInstance().readUser(userId);
                        if (tmp != null) {
                            userPhoto = tmp.getPhoto();
                            UserName = tmp.getUserName();
                        } else {
                            userPhoto = "photo url hardcoded";
                            UserName = "Torab Torabi hardcoded";
                        }

                        forumPost = new ForumPost(idPost, likeCount, text, isReported, isLiked, userId, groupId, true, date, userPhoto, UserName);
                        list.add(forumPost);
                    }

                    dbInstance.closeConnection();

                } catch (SQLException ex) {
//                    ex.printStackTrace();
                    Logger.getLogger(DBHandler.class.getName()).log(Level.SEVERE, null, ex);
                }
            }

        } catch (Exception e) {
//            e.printStackTrace();
            System.out.println("Error: " + e);
            logger.error("ERROR: " + ForumPostDaoImpl.class.getName() + ", " + e);
        }
        return list;
    }

    /**
     * Retrieves the forum for a resource having its ID.
     * @param resourceId
     * @return list of forum posts.
     */
    @Override
    public ArrayList<ForumPost> readResourceForum(Integer resourceId) {
        DBHandler dbInstance = DBHandler.getInstance();
        ArrayList<ForumPost> list = new ArrayList<ForumPost>();
        ForumPost forumPost;
        Integer idPost;
        Integer likeCount;
        String text;
        boolean isReported;
        boolean isLiked;
        Integer userId;
        Date date;

        //Added fields for business logic
        String userPhoto;
        String UserName;

        try {
            if (dbInstance != null) {
                String query = new String("SELECT * FROM ForumPost WHERE groupId = " + resourceId + " AND belongsToGroup = false");

                dbInstance.openConnection();
                ResultSet rs = dbInstance.executeQuery(query);

                try {
                    while (rs.next()) {
                        idPost = Integer.valueOf(rs.getInt("idPost"));
                        likeCount = Integer.valueOf(rs.getInt("likeCount"));
                        text = rs.getString("text");
                        isReported = rs.getBoolean("isReported");
                        isLiked = rs.getBoolean("isLiked");
                        userId = Integer.valueOf(rs.getInt("userId"));
                        date = rs.getDate("date");

                        //Call User to find out name and photo
                        User tmp = UserDaoImpl.getInstance().readUser(userId);
                        if (tmp != null) {
                            userPhoto = tmp.getPhoto();
                            UserName = tmp.getUserName();
                        } else {
                            userPhoto = "images/torab.png";
                            UserName = "Torab Torabi hardcoded";
                        }

                        forumPost = new ForumPost(idPost, likeCount, text, isReported, isLiked, userId, resourceId, false, date, userPhoto, UserName);
                        list.add(forumPost);
                    }

                    dbInstance.closeConnection();

                } catch (SQLException ex) {
//                    ex.printStackTrace();
                    Logger.getLogger(DBHandler.class.getName()).log(Level.SEVERE, null, ex);
                }
            }

        } catch (Exception e) {
//            e.printStackTrace();
            System.out.println("Error: " + e);
            logger.error("ERROR: " + ForumPostDaoImpl.class.getName() + ", " + e);
        }
        return list;
    }

    /**
     * Save a new post to a forum.
     * @param post
     * @param belongsToGroup indicates if this is a group or resource forum.
     * @return id of the recently inserted forum post.
     */
    @Override
    public Integer postToForum(ForumPost post, boolean belongsToGroup) {
//        System.err.println("post To Forum --------------- ");
        Integer postId = null;
        //The only information coming from the interface is the text, userId and groupOrResourceId
        //Here we generate the rest of the information
        post.setLikeCount(Integer.valueOf(0));
        post.setIsResported(false);
        post.setIsLiked(false);
        post.setBelongsToGroup(belongsToGroup);//Indicates true if this is a forumPost from a group, or false if it is related to a resource.
//        System.out.println(post.toString());

        //Forum Post bad word filter
        post.setText(filterPost(post.getText()));

        //Now save it to the database
        DBHandler dbInstance = DBHandler.getInstance();
        try {
            if (dbInstance != null) {

                String query = new String("INSERT INTO  ForumPost (likeCount, text, isReported, userId, "
                        + "groupId, belongsToGroup, isLiked, date)"
                        + " values (?, ?, ?, ?, ? , ?, ?, ?)");
                conn = dbInstance.openConnection();

                try {
                    PreparedStatement preparedStatement = null;
                    // PreparedStatements can use variables and are more efficient
                    preparedStatement = conn.prepareStatement(query, PreparedStatement.RETURN_GENERATED_KEYS);
                    // Parameters start with 1
                    preparedStatement.setInt(1, post.getLikeCount());
                    preparedStatement.setString(2, post.getText());
                    preparedStatement.setBoolean(3, false);
                    preparedStatement.setInt(4, post.getUserId());
                    preparedStatement.setInt(5, post.getGroupOrResourceId());
                    preparedStatement.setBoolean(6, post.getBelongsToGroup());
                    preparedStatement.setBoolean(7, post.getIsLiked());
                    preparedStatement.setDate(8, new java.sql.Date(new java.util.Date().getTime()));

                    preparedStatement.execute();

                    // fetch the latest groupId inserted
                    postId = fetchForumPostId(preparedStatement);

                    dbInstance.closeConnection();

                } catch (SQLException ex) {
                    ex.printStackTrace();
//                    Logger.getLogger(DBHandler.class.getName()).log(Level.SEVERE, null, ex);
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
//            System.out.println("Error: " + e);
//            logger.error("ERROR: " + ForumPostDaoImpl.class.getName() + ", " + e);
        }
        return postId;
    }

    /**
     * Gets the recently inserted forum post Id.
     * @param statement
     * @return forumPostId just inserted.
     */
    public Integer fetchForumPostId(PreparedStatement statement) {
        Integer id = null;

        ResultSet generatedKeys = null;

        try {

            generatedKeys = statement.getGeneratedKeys();
            if (generatedKeys.next()) {
                id = generatedKeys.getInt(1);
            } else {
                throw new SQLException("Creating forumPost id failed, no generated key obtained.");
            }

        } catch (SQLException e) {
            e.printStackTrace();
//            System.out.println("Error: " + e);
//            logger.error("ERROR: " + ForumPostDaoImpl.class.getName() + ", " + e);
        } finally {
            if (generatedKeys != null) {
                try {
                    generatedKeys.close();
                } catch (SQLException logOrIgnore) {
                    logOrIgnore.printStackTrace();
                }
            }
        }
        return id;

    }

    /**
     * Updates all the information of a forum post.
     * @param post 
     */
    @Override
    public void updatePost(ForumPost post) {

        DBHandler dbInstance = DBHandler.getInstance();

        try {
            if (dbInstance != null) {
                String query = new String("UPDATE  ForumPost SET likeCount = ?, text = ?, isReported = ?, isLiked = ?"
                        + " WHERE idPost = ?");
                conn = dbInstance.openConnection();

                try {
                    PreparedStatement preparedStatement = null;
                    // PreparedStatements can use variables and are more efficient
                    preparedStatement = conn.prepareStatement(query);
                    // Parameters start with 1
                    preparedStatement.setInt(1, post.getLikeCount());
                    preparedStatement.setString(2, post.getText());
                    preparedStatement.setBoolean(3, post.getIsResported());
                    preparedStatement.setBoolean(4, post.getIsLiked());
                    preparedStatement.setInt(5, post.getIdPost());

                    preparedStatement.executeUpdate();

                    dbInstance.closeConnection();

                } catch (SQLException ex) {
                    ex.printStackTrace();
//                    Logger.getLogger(DBHandler.class.getName()).log(Level.SEVERE, null, ex);
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
//            System.out.println("Error: " + e);
//            logger.error("ERROR: " + ForumPostDaoImpl.class.getName() + ", " + e);
        }
    }

    /**
     * Increases the likes count of a forum post and relates it to a user.
     * @param postId 
     */
    @Override
    public void likePost(Integer postId) {

        ForumPost tempP = readForumPost(postId);
        tempP.setLikeCount(tempP.getLikeCount() + 1);

        DBHandler dbInstance = DBHandler.getInstance();

        try {
            if (dbInstance != null) {
                String query = new String("UPDATE  ForumPost SET likeCount = ?, isLiked = ?"
                        + " WHERE idPost = ?");
                conn = dbInstance.openConnection();

                try {
                    PreparedStatement preparedStatement = null;
                    // PreparedStatements can use variables and are more efficient
                    preparedStatement = conn.prepareStatement(query);
                    // Parameters start with 1
                    preparedStatement.setInt(1, tempP.getLikeCount());
                    preparedStatement.setBoolean(2, true);
                    preparedStatement.setInt(3, postId);

                    preparedStatement.executeUpdate();

                    dbInstance.closeConnection();

                } catch (SQLException ex) {
                    ex.printStackTrace();
//                    Logger.getLogger(DBHandler.class.getName()).log(Level.SEVERE, null, ex);
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
//            System.out.println("Error: " + e);
//            logger.error("ERROR: " + ForumPostDaoImpl.class.getName() + ", " + e);
        }
    }

    /**
     * Reports a post.
     * @param postId 
     */
    @Override
    public void reportPost(Integer postId) {

        ForumPost tempP = readForumPost(postId);
        tempP.setLikeCount(tempP.getLikeCount() + 1);

        DBHandler dbInstance = DBHandler.getInstance();

        try {
            if (dbInstance != null) {
                String query = new String("UPDATE  ForumPost SET isReported = ?"
                        + " WHERE idPost = ?");
                conn = dbInstance.openConnection();

                try {
                    PreparedStatement preparedStatement = null;
                    // PreparedStatements can use variables and are more efficient
                    preparedStatement = conn.prepareStatement(query);
                    // Parameters start with 1
                    preparedStatement.setBoolean(1, true);
                    preparedStatement.setInt(2, postId);

                    preparedStatement.executeUpdate();

                    dbInstance.closeConnection();

                } catch (SQLException ex) {
                    ex.printStackTrace();
//                    Logger.getLogger(DBHandler.class.getName()).log(Level.SEVERE, null, ex);
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
//            System.out.println("Error: " + e);
//            logger.error("ERROR: " + ForumPostDaoImpl.class.getName() + ", " + e);
        }
    }

    /**
     * Retrieves a forum post.
     * @param postId
     * @return 
     */
    public ForumPost readForumPost(Integer postId) {
        DBHandler dbInstance = DBHandler.getInstance();
        ForumPost forumPost = new ForumPost();
        Integer idPost;
        Integer likeCount;
        String text;
        boolean isReported;
        boolean isLiked;
        Integer userId;
        Integer groupId;
        Date date;

        //Added fields for business logic
        String userPhoto;
        String UserName;

        try {
            if (dbInstance != null) {
                String query = new String("SELECT * FROM ForumPost WHERE idPost = " + postId);

                dbInstance.openConnection();
                ResultSet rs = dbInstance.executeQuery(query);

                try {
                    while (rs.next()) {
                        idPost = Integer.valueOf(rs.getInt("idPost"));
                        likeCount = Integer.valueOf(rs.getInt("likeCount"));
                        text = rs.getString("text");
                        isReported = rs.getBoolean("isReported");
                        isLiked = rs.getBoolean("isLiked");
                        userId = Integer.valueOf(rs.getInt("userId"));
                        groupId = Integer.valueOf(rs.getInt("groupId"));
                        date = rs.getDate("date");

                        //Call User to find out name and photo
                        User tmp = UserDaoImpl.getInstance().readUser(userId);
                        if (tmp != null) {
                            userPhoto = tmp.getPhoto();
                            UserName = tmp.getUserName();
                        } else {
                            userPhoto = "images/torab.png";
                            UserName = "Torab Torabi hardcoded";
                        }

                        forumPost = new ForumPost(idPost, likeCount, text, isReported, isLiked, userId, groupId, true, date, userPhoto, UserName);
                    }

                    dbInstance.closeConnection();

                } catch (SQLException ex) {
                    ex.printStackTrace();
//                    Logger.getLogger(DBHandler.class.getName()).log(Level.SEVERE, null, ex);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
//            System.out.println("Error: " + e);
//            logger.error("ERROR: " + ForumPostDaoImpl.class.getName() + ", " + e);
        }
        return forumPost;
    }

    /**
     * Deletes bad words from a forum post to avoid inappropriate content.
     * @param message
     * @return 
     */
    private static String filterPost(String message) {
        List<String> badWords = Arrays.asList("badword", "fuck", "fucking", "shit", "ahole", "anus", "ash0le", "ash0les", "asholes", "ass", "Ass Monkey", "Assface", "assh0le", "assh0lez", "asshole", "assholes", "assholz", "asswipe", "azzhole", "bassterds", "bastard", "bastards", "bastardz", "basterds", "basterdz", "Biatch", "bitch", "bitches", "Blow Job", "boffing", "butthole", "buttwipe", "c0ck", "c0cks", "c0k", "Carpet Muncher", "cawk", "cawks", "Clit", "cnts", "cntz", "cock", "cockhead", "cock-head", "cocks", "CockSucker", "cock-sucker", "crap", "cum", "cunt", "cunts", "cuntz", "dick", "dild0", "dild0s", "dildo", "dildos", "dilld0", "dilld0s", "dominatricks", "dominatrics", "dominatrix", "dyke", "enema", "f u c k", "f u c k e r", "fag", "fag1t", "faget", "fagg1t", "faggit", "faggot", "fagit", "fags", "fagz", "faig", "faigs", "fart", "flipping the bird", "fuck", "fucker", "fuckin", "fucking", "fucks", "Fudge Packer", "fuk", "Fukah", "Fuken", "fuker", "Fukin", "Fukk", "Fukkah", "Fukken", "Fukker", "Fukkin", "g00k", "gay", "gayboy", "gaygirl", "gays", "gayz", "God-damned", "h00r", "h0ar", "h0re", "hells", "hoar", "hoore", "jackoff", "jap", "japs", "jerk-off", "jisim", "jiss", "jizm", "jizz", "knob", "knobs", "knobz", "kunt", "kunts", "kuntz", "Lesbian", "Lezzian", "Lipshits", "Lipshitz", "masochist", "masokist", "massterbait", "masstrbait", "masstrbate", "masterbaiter", "masterbate", "masterbates", "Motha Fucker", "Motha Fuker", "Motha Fukkah", "Motha Fukker", "Mother Fucker", "Mother Fukah", "Mother Fuker", "Mother Fukkah", "Mother Fukker", "mother-fucker", "Mutha Fucker", "Mutha Fukah", "Mutha Fuker", "Mutha Fukkah", "Mutha Fukker", "n1gr", "nastt", "nigger", "nigur", "niiger", "niigr", "orafis", "orgasim",
                "orgasm", "orgasum", "oriface", "orifice", "orifiss", "peeenus", "peeenusss", "peenus", "peinus", "pen1s", "penas", "penis", "penis-breath", "penus", "penuus", "Phuc", "Phuck", "Phuk", "Phuker", "Phukker", "Poonan", "pr1c", "pr1ck", "pr1k", "pusse", "pussee", "pussy", "puuke", "puuker", "queer", "queers", "queerz", "qweers", "qweerz", "qweir", "recktum", "rectum", "retard", "sadist", "scank", "schlong", "screwing", "semen", "sex", "sexy", "Sh!t", "sh1t", "sh1ter", "sh1ts", "sh1tter", "sh1tz", "shit", "shits", "shitter", "Shitty", "Shity", "shitz", "Shyt", "Shyte", "Shytty", "Shyty", "skanck", "skank", "skankee", "skankey", "skanks", "Skanky", "slut", "sluts", "Slutty", "slutz", "son-of-a-bitch", "tit", "turd", "va1jina", "vag1na", "vagiina", "vagina", "vaj1na", "vajina", "vullva", "vulva", "w0p", "wh00r", "wh0re", "whore", "xrated", "xxx", "b!+ch", "bitch", "blowjob", "clit", "arschloch", "fuck", "shit", "ass", "asshole", "b!tch", "b17ch", "b1tch", "bastard", "bi+ch", "boiolas", "buceta", "c0ck", "cawk", "chink", "cipa", "clits", "cock", "cum", "cunt", "dildo", "dirsa", "ejakulate", "fatass", "fcuk", "fuk", "fux0r", "hoer", "hore", "jism", "kawk", "l3itch", "l3i+ch", "lesbian", "masturbate", "masterbat", "masterbat3", "motherfucker", "s.o.b. ", "mofo", "nazi", "nigga", "nigger", "nutsack", "phuck", "pimpis", "pusse", "pussy", "scrotum", "sh!t", "shemale", "shi+", "sh!+ ", "slut", "smut", "teets", "tits", "boobs", "b00bs", "teez", "testical", "testicle", "titt", "w00se", "jackoff", "wank", "whoar", "whore", "damn", "dyke", "fuck", "shit", "amcik", "andskota", "arse", "assrammer", "ayir", "bi7ch", "bitch", "bollock", "breasts", "butt-pirate", "cabron", "cazzo", "chraa", "chuj", "Cock", "cunt", "d4mn", "daygo", "dego", "dick", "dike", "dupa", "dziwka", "ejackulate", "Ekrem", "Ekto", "enculer", "faen", "fag", "fanculo", "fanny", "feces", "feg", "Felcher", "ficken", "fitt", "Flikker", "foreskin", "Fotze", "futkretzn", "gay", "gook", "guiena", "h0r", "h4x0r", "hell", "helvete", "hoer", "honkey", "Huevon", "hui", "injun", "jizz",  "muschi", "nazis", "nepesaurio", "nigger","pimmel", "piss", "pizda", "poontsee", "poop", "porn", "p0rn", "pr0n", "preteen", "pula", "pule", "puta", "puto", "qahbeh", "schlampe", "schmuck", "screw", "sharmuta", "sharmute", "shipal", "shiz", "skribz", "skurwysyn", "sphencter", "spic", "spierdalaj", "splooge", "suka", "twat", "vittu", "wank", "wetback", "wichser", "yed", "zabourah");
        for (String badWord : badWords) {
            message = message.replaceAll("(?i)\\b[^\\w -]*" + badWord + "[^\\w -]*\\b", "*");
        }
//        System.out.println(message);
        return message;
    }

    public static void main(String args[]) {
        System.out.println(filterPost("omg and smth shit. fuck fucking orifiss"));
    }
}
